iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0
自我挑戰組

從C到JS的同步非同步探索系列 第 20

[Day 20] Node 註冊事件 1

  • 分享至 

  • xImage
  •  

前言

昨天我們聊到, node 的 JS 層中的 IO method , 在作了相應的設定後, 就利用 XXX.on 這類 node api 把事件與其回調函數註冊進 libuv 了, 其中 libuv 就是 node 處理非同步 IO 的地方, 之後細聊, 今天我們先來了解, JS 把事件及其回調函數註冊進 libuv 這件事的本質是甚麼。

node 架構

https://ithelp.ithome.com.tw/upload/images/20210920/201311647f36Bh0sb9.png

觀察這張圖, 其中 APPLICATION 就是我們平常撰寫的 JS 程式碼, 而 V8 則是大名鼎鼎的 JS 驅動引擎,

https://zh.wikipedia.org/wiki/V8_(JavaScript引擎)

其實如果到此為止那就是我們一般看到的網頁結構。

而今天 node 在 V8 下面加上了 C++ 連接層, 此外 V8 在運行的時候可以在跑到特定 JS 程式碼時聯繫到 C++ 連階層的程式碼。而會被 V8 驅動引擎聯繫到 C++ 連階層的 JS 程式碼, 我個人稱之為 Node api, 而 C++ 連接層會再把透過 node api 傳入的事件及其回調函數 , 註冊進更底層的 Libuv

所以我們等下來看看 node API 是怎麼聯繫到 C++ 連接層。

正文

從昨天的進度開始往下走, 我們來看看我們註冊事件的對象 socket 的本體

https://github.com/nodejs/node/blob/master/lib/net.js

在裡面可以看到再標頭處的引用

**const { guessHandleType } = internalBinding('util');
const { ShutdownWrap } = internalBinding('stream_wrap');
const {
  TCP,
  TCPConnectWrap,
  constants: TCPConstants
} = internalBinding('tcp_wrap');
const {
  Pipe,
  PipeConnectWrap,
  constants: PipeConstants
} = internalBinding('pipe_wrap');**

其中 TCP 創建了 handle

function createHandle(fd, is_server) {
  validateInt32(fd, 'fd', 0);
  const type = guessHandleType(fd);
  if (type === 'PIPE') {
    return new Pipe(
      is_server ? PipeConstants.SERVER : PipeConstants.SOCKET
    );
  }

  if (type === 'TCP') {
    return new TCP(
      is_server ? TCPConstants.SERVER : TCPConstants.SOCKET
    );
  }

  throw new ERR_INVALID_FD_TYPE(type);
}

handle 被放在 socket 裡, 用來處理 node api

if (options.handle) {
    this._handle = options.handle; // private
    this[async_id_symbol] = getNewAsyncId(this._handle);
  } else if (options.fd !== undefined) {
    const { fd } = options;
    let err;

    // createHandle will throw ERR_INVALID_FD_TYPE if `fd` is not
    // a valid `PIPE` or `TCP` descriptor
    this._handle = createHandle(fd, false);

    err = this._handle.open(fd);
// 後略

至此我們知道了下一步就是察看 TCP 物件, 而此時發現引用 TCP 物件用的是internalBinding('tcp_wrap');

這再 V8 的意思就是引入 C++ 檔案

終於, 我們找到了被 V8 驅動引擎聯繫到 C++ 連接層的 JS 程式碼

明天進度

查看 TCP 的來源, C++連接層中的 tcp_wrap 把事件及回調函數註冊到哪了 ?

明天見 !


上一篇
[Day 19] Node http request
下一篇
[Day 21] Node 註冊事件 2
系列文
從C到JS的同步非同步探索30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言